Skip to content

在 ASP.NET Core MVC 使用 HTML5 實現多檔案上傳

TLDR

  • 使用 HTML5 的 <input type="file" multiple> 屬性即可啟用多檔案選取功能。
  • 前端應使用 FormData 物件封裝檔案資料,並透過 Axios 的 onUploadProgress 事件監聽 progressEvent 來實作上傳進度條。
  • 後端在 ASP.NET Core 中,應使用 IFormFileCollection 型別來接收多檔案繫結。
  • 預設的檔案上傳大小受限,可透過 FormOptions、Kestrel 設定或 [RequestSizeLimit] Attribute 進行調整。
  • 若使用 FormData 進行 Ajax 上傳,請勿手動設定 Content-Typemultipart/form-data,瀏覽器會自動處理。

前端實作:FormData 與進度監聽

什麼情況下會遇到這個問題:當需要透過 Ajax 非同步上傳多個檔案,並希望在前端顯示即時上傳進度時。

使用 FormData 可以將檔案資料封裝為 Key/Value 格式。在 Axios 中,透過 onUploadProgress 回呼函式,可以取得 loaded(已加載量)與 total(總量),進而計算上傳百分比。

程式碼範例

javascript
new Vue({
    el: '#app',
    data: {
        formData: new FormData,
        progressBarValue: 0
    },
    methods: {
        handleFileChange(e) {
            this.formData = new FormData();
            for (let i = 0; i < e.target.files.length; i++) {
                this.formData.append(e.target.id, e.target.files[i]);
            }
        },
        handleSubmit() {
            let config = {
                onUploadProgress: progressEvent => {
                    this.progressBarValue = (progressEvent.loaded / progressEvent.total * 100 | 0);
                }
            };

            axios.post('@Url.Action("Index3")', this.formData, config).then(response => {
                alert(response.data.message);
            }).catch(thrown => {
                alert(thrown);
            });
        }
    }
});

後端實作:IFormFileCollection 繫結

什麼情況下會遇到這個問題:當後端 Controller 需要接收來自前端傳送的多個檔案物件時。

ASP.NET Core 提供了 IFormFileCollection 介面,專門用於處理多檔案上傳的繫結。

ViewModel 與 Controller 範例

csharp
public class IndexViewModel {
    [DisplayName("上傳檔案")]
    [Required]
    public IFormFileCollection Files { get; set; }
}

[HttpPost]
public async Task<IActionResult> Index3(IndexViewModel viewModel) {
    if (!ModelState.IsValid) {
        // 錯誤處理邏輯
        return Ok(new { Message = "驗證失敗" });
    }

    foreach (var formFile in viewModel.Files) {
        if (formFile.Length > 0) {
            var filePath = Path.GetTempFileName();
            using var stream = System.IO.File.Create(filePath);
            await formFile.CopyToAsync(stream);
        }
    }
    return Ok(new { Message = "上傳成功" });
}

調整檔案上傳大小限制

什麼情況下會遇到這個問題:當上傳較大檔案時,伺服器因預設限制(如 MultipartBodyLengthLimit)而拒絕請求。

若需調整限制,可透過全域設定或針對特定 Action 使用 Attribute。

設定方式

  • 全域設定 (Program.cs)
csharp
builder.Services.Configure<FormOptions>(x => {
    x.MultipartBodyLengthLimit = 104857600; // 設定為 100MB
});
  • Action 屬性設定
csharp
[HttpPost]
[RequestSizeLimit(104857600)]
[RequestFormLimits(MultipartBodyLengthLimit = 104857600)]
public async Task<IActionResult> Index(IndexViewModel viewModel) {
    //...
}

DANGER

注意事項

  • 設定數值單位皆為 byte。
  • Attribute 的優先度高於全域設定。
  • 請依照實際業務需求設置合理的大小限制,避免資安風險。

異動歷程

    • 初版文件建立。